#!/usr/bin/python

import sys, os, time
import MySQLdb
from os.path import isfile

from pdb import set_trace

LOGFILE = "/var/log/kern.log"
#LOGFILE = "/home/ubuntu/Desktop/ipcontext/logger/1.txt"
CFGFILE = "logger.cfg"


################################################################
# Function: logger
#
# 1. connects to sql server
# 2. read kern.log
# 3. parse fw lines and add them to the log table in sql server
#
def logger():   
    try:
        conn = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "FW")
        cursor = conn.cursor () 
    except MySQLdb.Error, e:
        print "Error %d: %s" % (e.args[0], e.args[1])
        sys.exit (1)     
        
    fin = open(LOGFILE,"r")
	
    restart_log(fin)
    while 1:
        time.sleep(0.01)
        res = run_parser(fin)
        if res:
            _time         = res[0]
            _direction    = res[1]
            _srcIP        = res[2]
            _dstIP        = res[3]
            _srcPort      = res[4]
            _dstPort      = res[5]
            _protocol     = res[6]
            _rulePort     = res[7]
            _ruleProtocol = res[8]
            _action       = res[9]
                  
            try:
                cursor.execute ("""
                INSERT INTO Log (time, direct, sourceIP, destIP, sourcePort, destPort, protocol, rulePort, ruleProtocol, action)
                VALUES
                    ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')
                """ %(_time, _direction, _srcIP, _dstIP, _srcPort, _dstPort, _protocol, _rulePort, _ruleProtocol, _action))
            except MySQLdb.Error, e:
                print "Error %d: %s" % (e.args[0], e.args[1])
                sys.exit (1)

##################################################################
# Function: restart_log
# Input: file descripor (kern.log)
# Open config file which contain the latest line of the "kern.log"
# which was read by the parser and seek the file descriptor to 
# this line.
#
def restart_log(fin):

    if isfile(CFGFILE):
        fcfg = open(CFGFILE, "r")
        cfg = fcfg.readline().strip()
        fcfg.close()

        line = fin.readline().strip()
        while line:
            if cfg == line:
                break
            line = fin.readline().strip()

        if not line:
            fin.seek(0,0)


##################################################################
# Function: run_parser
# Input: file descripor (kern.log)
# Reade a line from given filed descriptor, parse it and return 
# the paramters which should be inserted into the SQL table
#
def run_parser(fin):
    line = fin.readline().strip()
    if line:
        save_log(line)
       
    if "OSLFW" in line: 
        log_fields = line.split()
        if (len(log_fields) != 18) and (len(log_fields) != 25):
            return None
                
        _time         = get_time(log_fields)
        _direction    = get_direction(log_fields)
        _srcIP        = get_srcIP(log_fields)
        _dstIP        = get_dstIP(log_fields)
        _srcPort      = get_srcPort(log_fields)
        _dstPort      = get_dstPort(log_fields)
        _protocol     = get_protocol(log_fields)
        _rulePort     = get_rulePort(log_fields)
        _ruleProtocol = get_ruleProtocol(log_fields)
        _action       = get_action(log_fields)
        
        return (_time, _direction, _srcIP, _dstIP, _srcPort, _dstPort, _protocol, _rulePort, _ruleProtocol, _action)
    
    else:
        return None


def save_log(line):
    fcfg = open(CFGFILE, "w")
    print >> fcfg, line
    fcfg.close()
 
#########################################
# Function: get_time
# Input: splited line
# parse the line and return the timestamp
#                
def get_time(log_fields):
    month = log_fields[0]
    day = int(log_fields[1])
    hour = log_fields[2]            
    month = int(time.strptime(month, "%b")[1])
    year  = int(time.localtime()[0])
    date = "%04d-%02d-%02d %s" % (year, month, day, hour)          
    return date


#########################################
# Function: get_direction
# Input: splited line
# parse the line and return the direction
#                    
def get_direction(log_fields):            
    if len(log_fields) == 18:
        if log_fields[8][3:] == "":
            direction = "In"
        else:
            direction = "Out"
    elif len(log_fields) == 25:
        if log_fields[6][9:] == "":
             direction = "In"
        else:
            direction = "Out"
    
    return direction
            

#########################################
# Function: get_srcIP
# Input: splited line
# parse the line and return the source IP
#                
def get_srcIP(log_fields):
    if len(log_fields) == 18:
        srcIP = log_fields[10][4:]
    elif len(log_fields) == 25:
        srcIP = log_fields[9][4:]

    return srcIP

    
#########################################
# Function: get_dstIP
# Input: splited line
# parse the line and return the destination IP
#                
def get_dstIP(log_fields):
    if len(log_fields) == 18:
        dstIP = log_fields[11][4:]
    elif len(log_fields) == 25:
        dstIP = log_fields[10][4:]
    
    return dstIP

    
#########################################
# Function: get_srcPort
# Input: splited line
# parse the line and return the source port
#                
def get_srcPort(log_fields):
    if len(log_fields) == 18:
        srcPort = log_fields[13][4:]
    elif len(log_fields) == 25:
        srcPort = log_fields[18][4:]
    
    return srcPort

    
###################################################
# Function: get_dstPort
# Input: splited line
# parse the line and return the destenation port
#                
def get_dstPort(log_fields):
    if len(log_fields) == 18:
        dstPort = log_fields[14][4:]
    elif len(log_fields) == 25:
        dstPort = log_fields[19][4:]

    return dstPort


############################################
# Function: get_protocol
# Input: splited line
# parse the line and return the protocol
#                
def get_protocol(log_fields):
    if len(log_fields) == 18:
        protocol = log_fields[12][6:]
    elif len(log_fields) == 25:
        protocol = log_fields[17][6:]

    return protocol
    

############################################
# Function: get_rulePort
# Input: splited line
# parse the line and return the rulePort
#                
def get_rulePort(log_fields):
    if len(log_fields) == 18:
        rulePort = log_fields[15][10:]
    elif len(log_fields) == 25:
        rulePort = ""
    
    return rulePort

    
###############################################
# Function: get_ruleProtocol
# Input: splited line
# parse the line and return the ruleProtocol
#                
def get_ruleProtocol(log_fields):
    if len(log_fields) == 18:
        ruleProtocol = log_fields[16][9:]
    elif len(log_fields) == 25:
        ruleProtocol = ""
    
    return ruleProtocol
    

#######################################################
# Function: get_action
# Input: splited line
# parse the line and return the action (Accept/Deny)
#                
def get_action(log_fields):
    if len(log_fields) == 18:
        if log_fields[17][7:-1] == "accepted":
            action = "Accept"
        else:
            action = "Deny"    
    elif len(log_fields) == 25:
        action = "Deny"
        
    return action


            

if __name__ == "__main__":
#    logger()
#    sys.exit(1)
    # do the UNIX double-fork magic, see Stevens' "Advanced 
    # Programming in the UNIX Environment" for details (ISBN 0201563177)
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit first parent
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    # decouple from parent environment
    os.chdir("/") 
    os.setsid() 
    os.umask(0) 
    # do second fork
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit from second parent, print eventual PID before
            print "Daemon PID %d" % pid 
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1) 

    # start the daemon main loop
    logger() 
